package funciones;

import principal.EstandarxDLG;
import genetico.AlgoritmoGenetico;

public class MetodoMomentos extends AlgoritmoGenetico {
	public double m1;
	public double m2;
	public double m3;
	public double m4;
	public double media;
	public double varianza;
	public double simetria;
	public double apuntamiento;
	public double desvEstandar;
	/**
	 * Alfas y alfas estimados
	 */
	public double a3, a4, ae1, ae2, ae3, ae4;
	public double errorAlpha3;
	public double errorAlpha4;

	public double A, B, C, D;
	public double me1, me2, me3, me4;
	//private double alfa3, alfa4, alfa3e, alfa4e;

	public MetodoMomentos() {
		super();
	}

	public MetodoMomentos(EstandarxDLG padre) {
		super(padre);
	}

	public void calcularMomentos(double muestra[]) {
		int i;
		// calcular la media
		m1 = 0;
		m2 = 0;
		m3 = 0;
		m4 = 0;

		for (i = 0; i < muestra.length; i++) {
			m1 += muestra[i];
		}
		m1 /= muestra.length;
		media = m1;
		System.out.println(m1);

		// varianza
		for (i = 0; i < muestra.length; i++) {
			m2 += (muestra[i] - m1) * (muestra[i] - m1);
		}
		m2 /= muestra.length;
		varianza = m2;

		desvEstandar = Math.sqrt(varianza);

		// momento3
		for (i = 0; i < muestra.length; i++) {
			m3 += Math.pow(muestra[i] - m1, 3);
		}
		m3 = m3 / (muestra.length * Math.pow(desvEstandar, 3));
		simetria = m3;
		// momento4
		for (i = 0; i < muestra.length; i++) {
			m4 += Math.pow(muestra[i] - m1, 4);
		}
		m4 = m4 / (muestra.length * Math.pow(desvEstandar, 4));
		apuntamiento = m4;
	}

	protected double calcularError() {
		return 0;
	}

	/**
	 * Sobreescribe el metodo
	 */
	public double calcularRendimiento(double cromosoma[]) {
		la1 = cromosoma[0];
		la2 = cromosoma[1];
		la3 = cromosoma[2];
		la4 = cromosoma[3];

		if ((la3 * la4) <= 0)
			return Double.MAX_VALUE;

		ae1 = media;
		ae2 = desvEstandar;
		ae3 = simetria;
		ae4 = apuntamiento;

		/*
		 * me1 =m1; me2 = desvEstandar; me3 = m3; me4 = m4;
		 */

		A = (1 / (1 + la3)) - (1 / (1 + la4));

		B = (1 / (1 + (2 * la3))) + (1 / (1 + (2 * la4)))
				- (2 * FuncionesProbabilidad.beta(1 + la3, 1 + la4));

		C = (1 / (1 + (3 * la3))) - (1 / (1 + (3 * la4)))
				- (3 * FuncionesProbabilidad.beta(1 + 2 * la3, 1 + la4))
				+ (3 * FuncionesProbabilidad.beta(1 + la3, 1 + 2 * la4));

		D = (1 / (1 + (4 * la3))) + (1 / (1 + (4 * la4)))
				- (4 * FuncionesProbabilidad.beta(1 + 3 * la3, 1 + la4))
				+ (6 * FuncionesProbabilidad.beta(1 + 2 * la3, 1 + 2 * la4))
				- (4 * FuncionesProbabilidad.beta(1 + la3, 1 + 3 * la4));

		// ae3 = m3;
		// ae4 = m4;

		// a3 =
		// (C-(3*A*B)+(2*(A*A*A)))/Math.abs(Math.pow((Math.sqrt(B-(A*A))),3));
		// a4 = (D-(4*A*C)+(6*(A*A)*B)-(3*Math.pow(A,4)))/Math.pow((B-(A*A)),2);
		// me1 = la1 + A/la2;
		// me2 = (B-(A*A))/(la2*la2);
		// m3 =
		// (C-(3*A*B)+(2*(A*A*A)))/Math.abs(Math.pow((Math.sqrt(B-(A*A))),3));
		// m4 = (D-(4*A*C)+(6*(A*A)*B)-(3*Math.pow(A,4)))/Math.pow((B-(A*A)),2);

		// me3=m3;
		// me4=m4;

		double temp1;
		temp1 = B - Math.pow(A, 2);
		if (temp1 >= 0) {
			a3 = (C - (3 * A * B) + (2 * Math.pow(A, 3)))
					/ Math.pow((Math.sqrt(B - Math.pow(A, 2))), 3);
			a4 = (D - (4 * A * C) + (6 * (Math.pow(A, 2)) * B) - (3 * Math.pow(
					A, 4)))
					/ Math.pow((B - (Math.pow(A, 2))), 2);
			double f = Math.pow(a3 - Math.abs(ae3), 2) + Math.pow(a4 - ae4, 2);
			// double f = Math.pow(Math.abs(m3-Math.abs(me3)),2)+
			// Math.pow(Math.abs(m4-Math.abs(me4)),2);

			// System.out.println("error: "+f);
			return f;
		} else
			return Double.MAX_VALUE;

		/*
		 * alfa3 = me3/Math.pow(me2, 1.5); alfa4 = me4/Math.pow(me2, 2); alfa3e =
		 * m3/Math.pow(m2, 1.5); alfa4e = m4/Math.pow(m2, 2);
		 */

		// return Math.pow((Math.abs((alfa3-Math.abs(alfa3e)))),2) +
		// Math.pow((Math.abs((alfa4-Math.abs(alfa4e)))),2);
	}

	public void ajustarLambdas(double cromosoma[]) {
		la1 = cromosoma[0];
		la2 = cromosoma[1];
		la3 = cromosoma[2];
		la4 = cromosoma[3];

		ae1 = media;
		ae2 = desvEstandar;
		ae3 = simetria;
		ae4 = apuntamiento;
		/*
		 * System.out.println("la1: "+la1); System.out.println("la2: "+la2);
		 * System.out.println("la3: "+la3); System.out.println("la4: "+la4);
		 * 
		 * me1 =m1; me2 = desvEstandar; me3 = m3; me4 = m4;
		 */

		A = (1 / (1 + la3)) - (1 / (1 + la4));

		B = (1 / (1 + (2 * la3))) + (1 / (1 + (2 * la4)))
				- (2 * FuncionesProbabilidad.beta(1 + la3, 1 + la4));

		C = (1 / (1 + (3 * la3))) - (1 / (1 + (3 * la4)))
				- (3 * FuncionesProbabilidad.beta(1 + 2 * la3, 1 + la4))
				+ (3 * FuncionesProbabilidad.beta(1 + la3, 1 + 2 * la4));

		D = (1 / (1 + (4 * la3))) + (1 / (1 + (4 * la4)))
				- (4 * FuncionesProbabilidad.beta(1 + 3 * la3, 1 + la4))
				+ (6 * FuncionesProbabilidad.beta(1 + 2 * la3, 1 + 2 * la4))
				- (4 * FuncionesProbabilidad.beta(1 + la3, 1 + 3 * la4));

		// ae3 = m3;
		// ae4 = m4;

		double temp1;
		temp1 = B - Math.pow(A, 2);
		if (temp1 >= 0) {
			a3 = (C - (3 * A * B) + (2 * Math.pow(A, 3)))
					/ Math.pow((Math.sqrt(B - Math.pow(A, 2))), 3);
			a4 = (D - (4 * A * C) + (6 * (Math.pow(A, 2)) * B) - (3 * Math.pow(
					A, 4)))
					/ Math.pow((B - (Math.pow(A, 2))), 2);

			errorAlpha3 = Math.abs(Math.abs(ae3) - Math.abs(a3));
			errorAlpha4 = Math.abs(ae4 - a4);
		}

		// me1 = la1 + A/la2;
		// me2 = (B-(A*A))/(la2*la2);
		// m3 =
		// (C-(3*A*B)+(2*(A*A*A)))/Math.abs(Math.pow((Math.sqrt(B-(A*A))),3));
		// m4 = (D-(4*A*C)+(6*(A*A)*B)-(3*Math.pow(A,4)))/Math.pow((B-(A*A)),2);

		// me3=m3;
		// me4=m4;

		double med = 0;
		double var = 1;

		la2 = Math.sqrt(B - (A * A)) / var;
		la1 = med - (A / la2);

		if (ae3 < 0) {
			double cambio;
			cambio = la3;
			la3 = la4;
			la4 = cambio;
			la1 = la1 * (-1);
		}

		la1 = la1 * ae2 + ae1;
		la2 = la2 / ae2;

		if (la3 < 0 && la4 < 0) {
			la2 = (-1) * la2 / ae2;
		}

	}

	public static void main(String[] args) {
		MetodoMomentos m = new MetodoMomentos();

		m.media = 2;
		m.varianza = 3;
		m.simetria = (-0.1581138830084);
		m.apuntamiento = 2;
		m.generaciones = 2000;
		m.poblacion = 200;
		m.probabilidadCruce = 0.5;
		m.probabilidadMutacion = 0.025;
		m.valorMax = 2;
		m.valorMin = (-1);
		m.errorMax = 1e-5;
		Thread t=new Thread(m);
		t.start();
		m.ajustarLambdas(m.mejorcromo);
		System.out.println("la1" + m.la1);
		m.ajustarLambdas(m.mejorcromo);
		System.out.println("la1 " + m.la1);
		System.out.println("la2 " + m.la2);
		System.out.println("la3 " + m.la3);
		System.out.println("la4 " + m.la4);
	}
}
